#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         AssessmentFilter.py
#
# Copyright:    Copyright (c) 2005, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  AssessmentFilters encapsulates the logic and state required
#               to 'filter' a collection of assessments.  At the highest 
#               level, a filter is simply a named, described, KERL expression
#               for a specific Model that may be used to determine
#               if an assessment satisfies a condition.
#
#               NOTE 1: This class does not perform the actual filtering.
#               It is used to hold state that is used to filter 
#               assessments.
#
#               NOTE 2: Instances of this class should always be pickable
#               using the marshal package as they are typically stored in 
#               HTTP sessions, forms and requests.
#
# See Also:     AssessmentStorateService
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Common import *
from KERLProcessor import compileKERLtoEnglish

#####################################################################
## Zope Library Imports
from Globals import InitializeClass
from AccessControl import ClassSecurityInfo
from AccessControl.Role import RoleManager
 
#####################################################################
## Python Library Imports
import base64, cPickle
import binascii

_MARKER = "_MARKER"

#---------------------------------------------------------------#

def decodeAssessmentFilterFromString(encodedAssessmentFilterString):
    """
        Returns an instance of the encoded assessment filter
        that was previously encoded with .encodeAsString()
    """

    return cPickle.loads(binascii.a2b_base64(encodedAssessmentFilterString))
    
#####################################################################
## AssessmentFilter Class Definition
class AssessmentFilter(RoleManager):
    """
        An object to represent assessment filter state.
    """
        
    #---------------------------------------------------------------#

    #declare security so ClassInfo may be accessed in DTML/ZPT etc
    security = ClassSecurityInfo()
    security.declareObjectPublic()
    security.setDefaultAccess("allow")

    #---------------------------------------------------------------#

    

    def __init__(self, title, expression, models=_MARKER, assessmentScope="*", model=_MARKER):
        """
            Assessment filters use kerlExpressions 
            
            Parameters:
            title : The name for the filter (commonly used for display purposes)
            expression : An object (not string) representation of a KERL that is to be used for filtering
            model : The model to which the filter applies
            assessmentScope : [String] - Is a list of actorIdentities that created the assessments. A value of ['*'] means everything. [] or None mean no assessments.            
            
            The parameter 'assessmentScope' is a list of actor identities (including groups)
            who (or whose members) have created a set of assessments.
            
            Additionally, the following constants for actor identities may be used;
            (these are appropriately substituted when compiling the SQL)
            
            '*'                             : all portal members.
            'authenticateduser'             : the currently authenticated user.
            'authenticatedusergroup'        : the members of the specified user's group
            'authenticatedusermanagedgroup' : the members of the groups that the specified user is managing
                
            Specifying a scope of None or [] means 0 is returned.
            
        """
        
        # Backwards compatibility- Some places still call init() with a kwarg of 'model'
        if model is not _MARKER:
            models = [model]
        
        if models is _MARKER:
            models = []
        
        if not type(models) in (list, tuple):
            models = [models]
        
        self.title = title
        self.expression = expression        #normalised KERL representation (not a string)
        self.modelIdentities = [model.getIdentity() for model in models]
        
        
        self.description = compileKERLtoEnglish(expression, model)
        
        
        self.assessmentScope = assessmentScope
    
    #---------------------------------------------------------------#

    def getTitle(self):
        """
            Returns the title of the filter
            
            RETURN TYPE: String
        """
        
        return self.title
    
    #---------------------------------------------------------------#

    def setTitle(self, title):
        """
            Sets the title of the filter
        """
        
        self.title = title
    
    #---------------------------------------------------------------#

    def getDescription(self):
        """
            Returns the english description of the filter
            
            RETURN TYPE: String
        """
        
        return self.description

    #---------------------------------------------------------------#

    def getModelIdentities(self):
        """
            Returns the model identity to which the filter is
            applicable
            
            RETURN TYPE: String
        """
        
        return self.modelIdentities
               
    #---------------------------------------------------------------#
        
    def getExpression(self):
        """
            Returns the normalised (non-string) representation 
            of the KERL expression for the filter
           
            RETURN TYPE: List
        """
        
        return self.expression
               
    #---------------------------------------------------------------#

    def setExpression(self, expression):
        """
            Sets the expression for the filter
        """

        if expression:
            self.expression = expression

    #---------------------------------------------------------------#
        
    def getAssessmentScope(self):
        """
            Returns the assessment scope used to further
            restrict the assessments returned for the filter
           
            RETURN TYPE: [String]
        """
        
        return self.assessmentScope
               
    #---------------------------------------------------------------#

    def encodeAsString(self):
        """
            Returns a string representing the instance so that it may
            be cPickled in and out of HTTP requests, sessions and/or
            HTML forms.
            
            Encoded filters may be decoded using the decodeAssessmentFilter
            method defined in this class
        """
        
        return binascii.b2a_base64(cPickle.dumps(self)).strip()

    #---------------------------------------------------------------#
        
#####################################################################
## Class Initialisation
InitializeClass(AssessmentFilter)
